package com.ansion.commonchat.util;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.text.TextUtils;

import com.ansion.basedb.dao.helper.ContactsHelper;
import com.ansion.basedb.dao.model.ContactsModel;
import com.ansion.commonchat.BaseApplication;
import com.ansion.commonchat.R;
import com.ansion.commonchat.contact.ContactsLoadManager;
import com.ansion.commonchat.contact.model.MatchContactModel;
import com.ansion.commonchat.contact.systemcontact.AndroidContactDB;
import com.ansion.commonchat.contact.systemcontact.AndroidContactsFactory;
import com.ansion.commonchat.contact.systemcontact.SystemContactUtils;
import com.ansion.constant.BConstant;
import com.ansion.log.VLog;
import com.ansion.utils.ContactUtil;
import com.ansion.utils.GsonUtil;
import com.ansion.utils.NetworkUtils;
import com.ansion.utils.ResourceUtils;
import com.ansion.utils.ServerTime;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;


/**
 * <pre>
 *     author : jake
 *     e-mail : hongjie.wang@ctechm.com
 *     time   : 2022/08/10 19:26
 *     function   : 联系人 功能入口及工具类
 * </pre>
 *
 * 跳转页面及接口请求
 */
public abstract class ContactGuideHelper {
    /**
     * 「从系统联系人页面返回的事件」标记。用于弹窗。
     *
     * 在此处接收到从系统联系人页面返回的事件，进行引导页弹出处理（为解决联系人二级页面的问题）
     * 问题描述：
     * 联系人修改完毕，会回到联系人二级页面，此时收到变更通知，直接拉起引导页；关闭引导页则会展示二级页面（与产品要求不符）
     *
     * 解决方案：
     * 1.本地存储变更内容（触发点是收到变更通知）
     * 2.本地存储是否收到「从系统联系人页面返回的事件」的标记。
     * 3.场景描述：
     * 场景一：
     * 先收到变更通知，存储数据，判断此时还未收到「从系统联系人页面返回的事件」，则不弹出；
     * 等收到 「从系统联系人页面返回的事件」，再弹出，同时清除本地数据
     * 场景二:
     * 先收到「从系统联系人页面返回的事件」，无存储数据，不弹出，至变更通知，直接弹出。而后清除数据。
     *
     * isOpenContact 标记
     * mChangedContactMap 临时存储的联系人变更的数据
     */
    public static boolean isOpenContact = false;
    public static Map<String, List<MatchContactModel>> changedContactMap;
    // 存储上次打开的 添加联系人 的时间
    public static long lastClickAddContactTime = 0;

    /**
     * formatPhone 有值，则说明可以格式化。无值直接返回phone，不用再次拼接+
     */
    public static String getPhonePlus(String formatPhone, String phone){
        if (TextUtils.isEmpty(formatPhone)){
            return phone;
        }
        String plusPhone;
        try {
            plusPhone = ContactUtil.getFormatPhone(Long.parseLong(formatPhone));
        } catch (NumberFormatException e){
            plusPhone = phone;
        }
        return plusPhone;
    }

    public static String getPhoneForInvite(String formatPhone, String phone){
        if (TextUtils.isEmpty(formatPhone)){
            return phone;
        }
        return formatPhone;
    }

    /**
     * 跳转到短信页，发送短信
     */
    public static void sendSmsToInvite(String phone){
        try {
            String smsInviteContent = "inviteContent";
            String body = TextUtils.isEmpty(smsInviteContent) ? BaseApplication.getContext().getResources()
                    .getString(R.string.baba_invite_sms) : smsInviteContent;
            Intent sendIntent = new Intent(Intent.ACTION_SENDTO);
            sendIntent.setData(Uri.parse("smsto:" + phone));
            sendIntent.putExtra("sms_body", body);
            sendIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            BaseApplication.getContext().startActivity(sendIntent);
        }catch(Exception e){
            e.printStackTrace();
        }
    }

    /**
     * 修改已存在的联系人信息
     */
    public static void editExistContact(Context context, String phone, Activity activity){
        int contactId = getContactId(phone);
        if(VLog.OPEN_LOG){
            VLog.d("TAG_CONTACT"," contact >> editContactInfo , phone : %s , contactId : %s",phone, contactId);
        }
        if (contactId == -1){
            return;
        }
        // 此处不能传入phone，因为要求的是直接编辑，如果传入phone，会默认添加手机号。
        SystemContactUtils.addToExistContact(contactId, "", activity);
    }

    private static int getContactId(String phone){
        //先获取raw_contacts表
        if (TextUtils.isEmpty(phone)){
            return -1;
        }
        try {
            ContactsModel userModel = ContactsHelper.getContact(Long.parseLong(phone));
            if (userModel != null){
                return userModel.getContactId();
            }
        } catch (NumberFormatException e){
            e.printStackTrace();
        }
        // 为了获取 ContactId ，在此处获取存储的联系人数据，取出 m_id ，即 ContactId
        Map<String, AndroidContactDB> contactPhoneDataMap = new HashMap<String, AndroidContactDB>(AndroidContactsFactory.getContactPhoneDataMap());
        AndroidContactDB db = contactPhoneDataMap.get(phone);
        if (VLog.OPEN_LOG) {
            VLog.d("TAG_CONTACT", " contact contactPhoneDataMap data %s ", GsonUtil.GsonString(contactPhoneDataMap));
        }
        if (db != null) {
            return db.getId();
        }
        return -1;
    }

    public static void showGuidePage(Map<String, List<MatchContactModel>> mChangedContactMap){
        if (VLog.OPEN_LOG) {
            VLog.d("TAG_CONTACT", " contact showGuidePage , checkShowGuidePage %s , isOpenContact %s , mChangedContactMap >>> %s , localChangedContactMap <<< %s , hasNetwork %s"
                    ,checkShowGuidePage(), isOpenContact, GsonUtil.GsonString(mChangedContactMap), GsonUtil.GsonString(changedContactMap),  NetworkUtils.hasNetwork(BaseApplication.getContext()));
        }
        if (checkShowGuidePage() && mChangedContactMap != null && checkContactRealUpdate(mChangedContactMap)) {
            List<MatchContactModel> addContacts = mChangedContactMap.get(BConstant.Contact.KEY_APPCONTACT_ADD);
            List<MatchContactModel> updateContacts = mChangedContactMap.get(BConstant.Contact.KEY_APPCONTACT_UPDATE);
            if ((addContacts != null && addContacts.size() > 0) || (updateContacts != null && updateContacts.size() > 0)) {
                /**
                 * 在此处进行是否应该展示的逻辑判断。
                 *
                 * 场景一：
                 * 先收到变更通知，存储数据，判断此时还未收到「从系统联系人页面返回的事件」，则不弹出；
                 * 等收到 「从系统联系人页面返回的事件」，再弹出，同时清除本地数据
                 * 场景二:
                 * 先收到「从系统联系人页面返回的事件」，无存储数据，不弹出，至变更通知，直接弹出。而后清除数据。
                 */
                if (isOpenContact){ // 尚未返回，不弹出，仅存储数据。
                    ContactGuideHelper.changedContactMap = mChangedContactMap;
                } else { // 已经返回，弹出，清除存储数据。
                    ContactGuideHelper.changedContactMap = null;
                    // 获取这需要传入的数据
                    List<MatchContactModel> contact = updateContacts;
                    if (addContacts != null  && addContacts.size() > 0) {
                        contact = addContacts;
                    }
                    MatchContactModel model = contact.get(0);
                    // 兼容小米、华为手机，返回的phone带空格。兼容美国手机号（去除中间的横线 +1929-399-3688 ）
                    String phone = model.getPhone().replaceAll(" ","").replaceAll("-","");
                    String name = model.getName();
                    // name 规则：用户未输入name，则显示所输入的手机号; 未输入name时，系统返回的name是phone。
                    if (TextUtils.isEmpty(name)){
                        name = phone;
                    }
                    if (TextUtils.isEmpty(phone)){
                        if (VLog.OPEN_LOG) {
                            VLog.d("TAG_CONTACT", " contact showGuidePage phone is empty");
                        }
                        return;
                    }
                    if (!checkCurrentContactPhones(phone)){
                        if (VLog.OPEN_LOG) {
                            VLog.d("TAG_CONTACT", " contact showGuidePage checkCurrentContactPhones is false");
                        }
                        return;
                    }
//                    ContactGuideActivity.startActivity(phone, name);
                    // 弹出之后，就要重置上次打开时间超出五分钟。
                    resetClickAddContactTime();
                }
            }
        }
    }

    /**
     * 因为重新登陆，也会收到更新联系人的通知，且数据为全量联系人数据。
     * 导致重新登陆时也会弹窗。
     *
     * 故，判断 KEY_APPCONTACT_ADD size 与 全量数据 size 相等，则忽略。
     */
    private static boolean checkContactRealUpdate(Map<String, List<MatchContactModel>> mChangedContactMap){
        boolean isUpdate = true;
        Map<String, AndroidContactDB> contactPhoneDataMap = new HashMap<String, AndroidContactDB>(AndroidContactsFactory.getContactPhoneDataMap());
        if (contactPhoneDataMap.size() > 0 && mChangedContactMap != null){
            List<MatchContactModel> addContacts = mChangedContactMap.get(BConstant.Contact.KEY_APPCONTACT_ADD);
            if (addContacts != null && contactPhoneDataMap.size() ==  addContacts.size()){
                isUpdate = false;
            }
        }
        if (VLog.OPEN_LOG) {
            VLog.d("TAG_CONTACT", " contact checkContactRealUpdate , isUpdate %s ", isUpdate);
        }
        return isUpdate;
    }

    /**
     * 获取当前联系人所有关联的手机号
     * 用于展示当前联系人所有手机列表。
     *
     * 数据源去除自己，不用做20个手机号限制，不弹窗即可。
     */
    public static Set<String> getCurrentContactPhones(String phone){
        Map<String, AndroidContactDB> contactPhoneDataMap = new HashMap<String, AndroidContactDB>(AndroidContactsFactory.getContactPhoneDataMap());
        AndroidContactDB db = contactPhoneDataMap.get(phone);
        if (db != null && db.getPhoneBeanMap() != null && db.getPhoneBeanMap().size() > 0) {
            if (VLog.OPEN_LOG) {
                VLog.d("TAG_CONTACT", " contact getCurrentContactPhones data %s ", GsonUtil.GsonString(db.getPhoneBeanMap().keySet()));
            }
            Set<String> data = db.getPhoneBeanMap().keySet();
            // 数据源中移除自己
            data.remove(getLoginPhone());
            data.remove(getUid());
            return data;
        }
        return null;
    }

    private static String getLoginPhone(){
        return "8618519291063";//AppBridge.getInstance().getAppInterface().getPhone();
    }

    private static String getUid(){
        return "8618519291063";//AppBridge.getInstance().getAppInterface().getUid() + "";
    }

    /**
     * 检查单个联系人数据是否合规
     * 1.超过20个手机号不弹，返回false
     * 2.是自己不弹，返回false (会忽略此手机号所带的其他手机号，故不做此判断，直接在数据源中移除自己即可)
     * 3.过滤后数据为空也不弹
     */
    public static boolean checkCurrentContactPhones(String phone){
        Map<String, AndroidContactDB> contactPhoneDataMap = new HashMap<String, AndroidContactDB>(AndroidContactsFactory.getContactPhoneDataMap());
        AndroidContactDB db = contactPhoneDataMap.get(phone);
        if (VLog.OPEN_LOG) {
            VLog.d("TAG_CONTACT", " contact showGuidePage checkCurrentContactPhones , db %s , phone %s , uid %s , loginPhone %s ",db,phone,getLoginPhone(),getUid());
        }
        if (db != null && db.getPhoneBeanMap() != null && db.getPhoneBeanMap().size() > 0) {
            Set<String> data = db.getPhoneBeanMap().keySet();
            // 超过20个手机号不弹
            if (data.size() > BConstant.Contact.LIMIT_NUM_SHOW_CONTACT){
                return false;
            }
            // 过滤后数据为空也不弹
            data.remove(getLoginPhone());
            data.remove(getUid());
            return !data.isEmpty();
        }
        return true;
    }

    /**
     * 检测是否在五分钟内，检测是否打开CC开关，检测是否在通话(呼叫、通话中)
     */
    private static boolean checkShowGuidePage(){
        return checkInFiveMin()
                && NetworkUtils.hasNetwork(BaseApplication.getContext());
    }

    /**
     * 判断点击过添加来联系人之后的五分钟内，才可以弹窗
     * 如果上一次点击添加联系人超过了五分钟，则不弹窗。
     *
     * 检查是否在5分钟内
     */
    private static boolean checkInFiveMin(){
        long currentTime = ServerTime.getServerTimeMillisecond();
        return currentTime - getClickAddContactTime() <= BConstant.Contact.COOL_DOWN_5_MIN;
    }

    // 故，此处存储的是上一次App中「打开添加联系人」的时间点。
    public static void saveClickAddContactTime(){
        lastClickAddContactTime = ServerTime.getServerTimeMillisecond();
    }

    // 此处重置的意思就是，直接赋值 超出当前时间5分钟的时间。此处直接赋值为0，则差值超出5分钟
    public static void resetClickAddContactTime(){
        lastClickAddContactTime = 0;
    }

    private static Long getClickAddContactTime(){
        return lastClickAddContactTime;
    }

    public static void logout(){
        changedContactMap = null;
        isOpenContact = false;
        resetClickAddContactTime();
    }

    /**
     * 在此处接收到从系统联系人页面返回的事件，进行引导页弹出处理（为解决联系人二级页面的问题）
     *
     * 此处要做的事，详细描述见 ContactGuideHelper：
     * 1.判断是否有存储数据，有则弹窗。
     * 2.重置 「从系统联系人页面返回的事件」标记。
     */
    public static boolean onActivityResult(int requestCode){
        if (requestCode == BConstant.Contact.REQUEST_CODE_EDIT_CONTACT){
            VLog.d("TAG_CONTACT"," onActivityResult , requestCode : %s ",requestCode);
            ContactGuideHelper.isOpenContact = false;
            AndroidContactsFactory.startContactQuery();
            ContactsLoadManager.getInstance().loadLocalContacts();
            if (ContactGuideHelper.changedContactMap == null) {
            } else {
                ContactGuideHelper.showGuidePage(ContactGuideHelper.changedContactMap);
            }
            return true;
        } else {
            VLog.e("TAG_CONTACT"," onActivityResult , requestCode : %s ",requestCode);
        }
        return false;
    }

}
